package patternmining.model.construction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @version 1.0, 05.07.2008
 * @author Holger Wiehen
 */

class MethodNameResolver {
    
    private Map<String,MethodNameVariants> registeredMethods;
    
    public MethodNameResolver(){
        registeredMethods = new HashMap<String, MethodNameVariants>();
    }
    
    public void addMethod( String qualifiedMethodName, String[] argumentTypes ){
       MethodNameVariants methodNameVariants = registeredMethods.get(qualifiedMethodName);
       if( methodNameVariants == null){
            methodNameVariants = new MethodNameVariants( qualifiedMethodName );
            registeredMethods.put(qualifiedMethodName, methodNameVariants);
       }
       methodNameVariants.addVariation(argumentTypes);
    }
    
    public String getUniqueMethodName( String qualifiedMethodName, String[] argumentTypes )throws UnknownMethodException{
         String uniqueName = null;
         MethodNameVariants methodNameVariants = registeredMethods.get(qualifiedMethodName);
         if( methodNameVariants == null){
             throw new UnknownMethodException(qualifiedMethodName, argumentTypes);
         }
         uniqueName = methodNameVariants.getUniqueName(argumentTypes);
         return uniqueName;
    }
    
    public String[] getRegisteredMethods(){
        Collection<MethodNameVariants> registered = registeredMethods.values();
        Collection<String> uniqueNames;
        List<String> allMethodNames = new ArrayList<String>();
        for( MethodNameVariants variants : registered ){
            uniqueNames = variants.uniqueNames.values();
            for( String name : uniqueNames){
                allMethodNames.add(name);
            }
        }
        return allMethodNames.toArray( new String[allMethodNames.size()] );
    }
    

    class MethodNameVariants{
        
        private String qualifiedMethodName;
        private int uniqueSuffix;
        private Map<String[],String> uniqueNames;
        
        public MethodNameVariants( String qualifiedMethodName ){
            this.qualifiedMethodName = qualifiedMethodName;
            this.uniqueSuffix = 0;
            uniqueNames = new HashMap<String[],String>();
        }
        
        public void addVariation(String[] argumentTypes){
            if( uniqueSuffix == 0 ){
                uniqueNames.put(argumentTypes, qualifiedMethodName);
            }
            else{
                uniqueNames.put(argumentTypes, qualifiedMethodName + "_" + uniqueSuffix);
            }
            uniqueSuffix++;
        }
        
        public String getUniqueName(String[] argumentTypes) throws UnknownMethodException{
            String uniqueName = null;
            String[] key = null;
            Set<String[]> paramTypes = uniqueNames.keySet();
            for( String[] methodVariation : paramTypes ){
                if( Arrays.equals( methodVariation, argumentTypes)){
                    key = methodVariation;
                }
            }
            
            uniqueName = uniqueNames.get(key);
            if( uniqueName == null ){
                throw new UnknownMethodException(qualifiedMethodName, argumentTypes);
            }
            return uniqueName;
        }
        
    }

}
